package br.edu.ufcg.embedded.util.algo;

import java.util.Collections;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;

import org.jgrapht.Graph;
import org.jgrapht.graph.DefaultEdge;

import br.edu.ufcg.embedded.domain.CustomVertex;
import br.edu.ufcg.embedded.domain.Visitor;
import br.embedded.socialapp.data.FriendshipDAO;

public class GraphGenerator3 {
	
	private Hashtable<String, Integer> internalCounters;
	private Hashtable<String, Float> calculated, target;
	private final int MAX_LEVELS = 1;
	
	public GraphGenerator3(Hashtable<String, Float> matrix) {
		
		this.target = matrix;
		initialize();
	}
	
	public Graph<String, DefaultEdge> generate(int sampleSize) {
		
		CustomVertex root = FriendshipDAO.getInstance().getRandomVertices("C", 1).get(0);
				
		//ArrayList<Integer> l1 = new ArrayList<Integer>(getFollowing(root));
		ArrayList<Integer> l1 = new ArrayList<Integer>(getFollowers(root));
		//l1.addAll(l2);
		Collections.sort(l1);
		System.out.println(l1.size());
		
		System.out.println("passou");
		Graph<String, DefaultEdge> graph = FriendshipDAO.getInstance().getSocialConnections(l1).getGraph();
		
		//calculate();
		
		/*System.out.println("Inicial >>> " + target);
		System.out.println("Final >>> " + calculated);
		System.out.println(internalCounters);*/

		return graph;
	}

	private Set<Integer> getFollowers(CustomVertex root) 
	{
		Queue<CustomVertex> queue = new LinkedList<CustomVertex>();
		Map<Integer, CustomVertex> map = new HashMap<Integer, CustomVertex>();

		map.put(root.getNumber(), root);
		queue.add(root);

		while ( !queue.isEmpty() ) {

			CustomVertex v1 = queue.remove();
			v1 = map.get(v1.getNumber());

			//System.out.println("v1: " + v1.getNumber() + " nivel: " + v1.getDistance() + " cor: " + v1.getColor());

			if (v1.getColor() == Visitor.WHITE) {

				v1.setColor(Visitor.GRAY);
				map.put(v1.getNumber(), v1);

				List<CustomVertex> list1 = FriendshipDAO.getInstance().getFollowers(v1);
				list1.remove(v1);
				list1.remove(root);

				//System.out.println("v1: " + v1.getNumber() + " nivel: " + v1.getDistance() + " cor: " + v1.getColor());

				for (CustomVertex n1 : list1)
				{	
					if (!map.containsKey(n1.getNumber())) {
						n1.setDistance(v1.getDistance() + 1);
						map.put(n1.getNumber(), n1);
					}

					n1 = map.get(n1.getNumber());

					//System.out.println("n1: " + n1.getNumber() + " nivel: " + n1.getDistance() + " cor: " + n1.getColor());

					if (n1.getColor() == Visitor.WHITE && n1.getDistance() <= MAX_LEVELS )
						queue.add(n1);
					else {
						n1.setColor(Visitor.BLACK);
						map.put(n1.getNumber(), n1);
					}
				}

				v1.setColor(Visitor.BLACK);
				map.put(v1.getNumber(), v1);
			}
		}
		System.out.println("Terminou2");
		return map.keySet();
	}
	
	private Set<Integer> getFollowing(CustomVertex root) {

		Queue<CustomVertex> queue = new LinkedList<CustomVertex>();
		Map<Integer, CustomVertex> map = new HashMap<Integer, CustomVertex>();

		map.put(root.getNumber(), root);
		queue.add(root);

		while ( !queue.isEmpty() ) {

			CustomVertex v1 = queue.remove();
			v1 = map.get(v1.getNumber());

			//System.out.println("v1: " + v1.getNumber() + " nivel: " + v1.getDistance() + " cor: " + v1.getColor());
			
			if (v1.getColor() == Visitor.WHITE) {
				
				v1.setColor(Visitor.GRAY);
				map.put(v1.getNumber(), v1);
				
				List<CustomVertex> list1 = FriendshipDAO.getInstance().getFollowing(v1);
				list1.remove(v1);
				list1.remove(root);

				//System.out.println("v1: " + v1.getNumber() + " nivel: " + v1.getDistance() + " cor: " + v1.getColor());

				for (CustomVertex n1 : list1)
				{	
					if (!map.containsKey(n1.getNumber())) {
						n1.setDistance(v1.getDistance() + 1);
						map.put(n1.getNumber(), n1);
					}

					n1 = map.get(n1.getNumber());

					//System.out.println("n1: " + n1.getNumber() + " nivel: " + n1.getDistance() + " cor: " + n1.getColor());

					if (n1.getColor() == Visitor.WHITE && n1.getDistance() <= MAX_LEVELS )
						queue.add(n1);
					else {
						n1.setColor(Visitor.BLACK);
						map.put(n1.getNumber(), n1);
					}
				}

				v1.setColor(Visitor.BLACK);
				map.put(v1.getNumber(), v1);
			}
		}
		System.out.println("Terminou1");
		return map.keySet();
	}
	
	/*private void calculate() {
		
		Iterator<String> it = internalCounters.keySet().iterator();
		int total = graphBuilder.getVerticesSize();
		
		while (it.hasNext()) {
			
			String key = it.next();
			float result = ((float) (internalCounters.get(key) * 1.000000000) / total);
			calculated.put(key, result);	
		}
	}
	
	private boolean checkCounters(int sampleSize) {
		
		Iterator<String> it = calculated.keySet().iterator();
		int total = graphBuilder.getVerticesSize();
		
		while (it.hasNext()) {
			
			String key = it.next();
			
			if ((calculated.get(key) >= target.get(key)) && total >= sampleSize)
				continue;
			else
				return false;
		}
		
		return true;
	}*/
	
	private void initialize()
	{
		this.internalCounters = new Hashtable<String, Integer>();
		this.calculated = new Hashtable<String, Float>();
		
		for (String key : target.keySet()) {
			
			this.internalCounters.put(key, new Integer(0));
			this.calculated.put(key, new Float(0.0));
		}
	}
}